import { ref, reactive, Ref, unref } from 'vue'
import { Node, Graph, CellView } from '@antv/x6'
import { Snapline } from '@antv/x6-plugin-snapline'
import { Transform } from '@antv/x6-plugin-transform'
import { History } from '@antv/x6-plugin-history'
import { Selection } from '@antv/x6-plugin-selection'
import { Clipboard } from '@antv/x6-plugin-clipboard'
import { Keyboard } from '@antv/x6-plugin-keyboard'
import { Message } from '@arco-design/web-vue'
import {
  getTransferNodeConfig,
  getNodeListForModules
} from '@/utils/transferNodeConfig'
import { FIELDS_PATH } from '@/config'
import { ColorEnum } from '@/enum/graph.enum'
import { MiniMap } from '@/components/x6-plugin-minimap'
import {
  batchSaveModules,
  exportCanvasJson,
  getCanvasPageModules,
  getCanvasPages,
  graphInfo,
  getCanvasFonts
} from '@/api/graph'
import { getSize, serializeRequestForm } from '@/utils'
import { getSense } from '@/utils/dict'
import { saveAs } from 'file-saver'
import type { NodeConfig } from '@/config/node.config'
import type { Font } from '@/utils/loadFont'

const defaultMiniMapScale:number = 0.3
export const useGraphCore = () => {
  const graphEditor:Ref<null|Graph> = ref(null)
  const nodeConfigForm = ref({})
  const selectNode:Ref<null|Node> = ref(null)
  const scaleCount:Ref<number> = ref(1)
  let nodeList:Node<Node.Properties>[] | undefined = []
  const fontList:Ref<Font[]> = ref([])
  const graphCoreData = reactive({
    width: 800,
    height: 400,
    color: 'black_white_red',
    backgroundColor: 'white',
    id: null,
    canvasKey: null,
    name: null,
    overlapRule: '2',
    size: '320×240',
    sizeType: '2.4',
  })
  const initCanvas = async ({width=800,height=400,element}) => {
    const bgColor = ColorEnum[graphCoreData.backgroundColor as keyof typeof ColorEnum].color || '#ffffff'
    const graphEditor:Graph = new Graph({
      container: element,
      width,
      height,
      panning: false,
      mousewheel: false,
      background: {
        color: bgColor
      },
      translating: {
        restrict: false
      },
      interacting:{
        nodeMovable(cellView:CellView) {
            const {cell} = cellView
          const { _isEnableMove } = cell.getData()
          return _isEnableMove
        },
      },

    })
    /**
     * 初始化插件
     * @param graphEditor
     */
    const initPlugins = (graphEditor:Graph) => {
      const { width, height } = graphCoreData
      // 对齐线
      graphEditor.use(
        new Snapline({
          enabled: true
        })
      )
      // 快捷键
      graphEditor.use(
        new Keyboard({
          enabled: true
        })
      )
      // 复制粘贴
      graphEditor.use(
        new Clipboard({
          enabled: true
        })
      )
      // 框选
      graphEditor.use(
        new Selection({
          enabled: true,
          multiple: false,
          rubberband: true,
          movable: true,
          showNodeSelectionBox: true
        })
      )
      // 撤销重做
      graphEditor.use(
        new History({
          enabled: true
        })
      )
      // 图形变换
      graphEditor.use(
        new Transform({
          resizing: {
            enabled: true,
            minWidth: 1,
            maxWidth: width,
            minHeight: 1,
            allowReverse: false,
            maxHeight: height,
            preserveAspectRatio (node:Node) {
              const { _isPreserveAspectRatio } = node.getData()
              return _isPreserveAspectRatio || false
            }
          },
          rotating: {
            enabled: true,
            grid: 5
          }
        })
      )
      graphEditor.use(
        new MiniMap({
          container: document.querySelector('#editor-minimap-content') as HTMLElement,
          width: width * defaultMiniMapScale,
          height: height * defaultMiniMapScale,
          padding: 0,
          graphOptions: {
            scaling: {
              min: defaultMiniMapScale,
              max: defaultMiniMapScale
            }
          }
        })
      )
    }
    /**
     * 初始化快捷键
     * @param graphEditor 实例
     */
    const initKeyboard = (graphEditor:Graph) => {
      // 复制
      graphEditor.bindKey(['meta+c', 'ctrl+c'], copyNodes)
      graphEditor.bindKey(['meta+v', 'ctrl+v'], pasteNodes)
      // delete
      graphEditor.bindKey('backspace', delNodes)
      // undo redo
      graphEditor.bindKey(['meta+z', 'ctrl+z'], () => {
        graphEditor.canUndo() ? graphEditor.undo() : false
      })
    }
    const initEvents = (graphEditor:Graph) => {
      const onChangeNodeList = () => {
        nodeList = graphEditor.getNodes()
      }
      graphEditor.on('node:added', (cell: { node:Node }) => {
        // 6-21增加放置次序的字段
        const nodes = graphEditor.getNodes()
        const maxSetIndex = Math.max(...nodes.map(node => {
          const data = node.getData()
          return data.setIndex || 0
        }))
        cell.node.setData({ ...cell.node.getData(), setIndex: maxSetIndex + 1 }, { silent: true })
        onChangeNodeList()
      })
      graphEditor.on('node:removed', onChangeNodeList)

      // 需要改变数据层
      graphEditor.on('node:resized', ({ node }) => {
        const { width, height } = node.size()
        onChangeNodeAttr({
          width: Math.round(width),
          height: Math.round(height)
        })
      })
      graphEditor.on('node:rotated', ({ node }) => {
        const rotate = node.getAngle()
        onChangeNodeAttr({
          rotate: Math.round(rotate)
        })
      })
      graphEditor.on('node:moved', ({ node }) => {
        const { x, y } = node.position()
        onChangeNodeAttr({
          startX: Math.round(x),
          startY: Math.round(y)
        })
      })
      graphEditor.on('node:click', ({ node }) => {
        console.log('click', node)
        onChangeSelectNode({
          nodeId: node.id,
          isNeedSelect: false
        })
      })

      graphEditor.on('blank:click', () => {
        console.log('blank:click')
        graphEditor.resetSelection()
        onChangeSelectNode({nodeId:null,isNeedSelect:false})
      })
    }
    initPlugins(graphEditor)
    initKeyboard(graphEditor)
    initEvents(graphEditor)
    return graphEditor
  }
  const addNode = (nodeConfig:NodeConfig) => {
    const config = {
      shape: nodeConfig.shape,
      data: nodeConfig.data,
      width: nodeConfig.data.width,
      height: nodeConfig.data.height,
      x: nodeConfig.data.startX,
      y: nodeConfig.data.startY
    }
    if (Object.prototype.hasOwnProperty.call(config.data, 'fontType')) {
      const defaultFontType:Font | undefined = fontList.value.find(item => item.isDefault === '1')
      if (defaultFontType) {
        config.data.fontType = config.data.fontType || defaultFontType.fontName
      }
    }
    const node = graphEditor.value?.addNode(config) as Node
    graphEditor.value?.clearTransformWidgets()
    onChangeSelectNode({
      nodeId: node.id,
      isNeedSelect: false
    })

  }
  const delNodes = () => {
    const cells = graphEditor.value?.getSelectedCells()
    if (cells && cells.length) {
      graphEditor.value?.removeCells(cells)
      // 删除节点时如果配置面板打开是需要进行判断
      if (selectNode.value) {
        const ids = cells.map((c) => c.id)
        if (ids.includes(selectNode.value.id)) {
          clearSelectNode()
        }
      }
    }
  }
  const clearSelectNode = () => {
    nodeConfigForm.value = {}
    selectNode.value = null
  }
  const clearGraph = () => {
    graphEditor.value?.clearCells()
    clearSelectNode()
  }
  const undoGraph = () => {
    graphEditor.value?.undo()
  }
  const redoGraph = () => {
    graphEditor.value?.redo()
  }
  const exportToGraph = () => {

  }
  const copyNodes = () => {
    const cells = graphEditor.value?.getSelectedCells()
    if (cells && cells.length) {
      graphEditor.value?.copy(cells)
    } else {
      Message.warning('请先选中节点再复制')
    }
  }
  const pasteNodes = () => {
    const editor = unref(graphEditor)
    if (editor?.isClipboardEmpty()) {
      Message.warning('剪切板为空，不可粘贴')
    } else {
      editor?.paste()
      editor?.cleanSelection()
      editor?.clearTransformWidgets()
    }
  }
  const onChangeSelectNode = (data :any) => {
    const {nodeId,isNeedSelect} = data
    console.log(nodeId,isNeedSelect)
  }
  const onChangeNodeAttr = (data: any) => {
    if (!selectNode.value) return
    const nodeData = selectNode.value?.getData()
    const basicAttributes = ['startX', 'startY', 'width', 'height', 'rotate']
    Object.keys(data).forEach(basicAttributesKey => {
      if (Object.prototype.hasOwnProperty.call(data, basicAttributesKey)) {
        nodeConfigForm.value?[basicAttributesKey] = data[basicAttributesKey] : null
        if (basicAttributes.includes(basicAttributesKey)) {
          selectNode.value?.prop(FIELDS_PATH[basicAttributesKey], data[basicAttributesKey])
        }
      }
    });
    selectNode.value?.setData({
      ...nodeData,
      ...data
    })
  }
  const onChangeGraphScale = (type: 'out'| 'in') => {
    const step = 0.05
    const minScale = 0.2
    const maxScale = 2
    // 计算新的缩放比例
    const newScale =
      type === 'out' ? scaleCount.value + step : scaleCount.value - step

    // 确保新的缩放比例在允许的范围内
    if (newScale >= minScale && newScale <= maxScale) {
      scaleCount.value = parseFloat(newScale.toFixed(2))
    }
  }

  return {
    graphEditor,
    exportToGraph,
    redoGraph,
    undoGraph,
    clearGraph,
    addNode,
    onChangeGraphScale,
    initCanvas
  }
}
